package cc.admin.modules.sys.service.impl;

import cc.admin.common.constant.CommonConstant;
import cc.admin.common.constant.FillRuleConstant;
import cc.admin.common.sys.vo.LoginUser;
import cc.admin.common.util.FillRuleUtil;
import cc.admin.modules.sys.entity.*;
import cc.admin.modules.sys.mapper.*;
import cc.admin.modules.sys.model.OrgIdModel;
import cc.admin.modules.sys.model.SysOrgTreeModel;
import cc.admin.modules.sys.service.ISysOrgService;
import cc.admin.modules.sys.util.FindsOrgsChildrenUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.netty.util.internal.StringUtil;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 机构表 服务实现类
 *
 * @Author
 * @Since 2022-07-07
 */
@Service
public class SysOrgServiceImpl extends ServiceImpl<SysOrgMapper, SysOrg> implements ISysOrgService {

    @Autowired
    private SysOrgMapper SysOrgMapper;

    /**
     * queryTreeList 对应 queryTreeList 查询所有的机构数据,以树结构形式响应给前端
     */
    @Override
    public List<SysOrgTreeModel> queryTreeList() {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<SysOrg> query = new LambdaQueryWrapper<SysOrg>();
        query.eq(SysOrg::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
        query.likeRight(SysOrg::getCode,sysUser.getSysOrgCode());
        query.orderByAsc(SysOrg::getSortBy);
        List<SysOrg> list = this.list(query);
        // 调用wrapTreeDataToTreeList方法生成树状数据
        List<SysOrgTreeModel> listResult = FindsOrgsChildrenUtil.wrapTreeDataToTreeList(list);
        return listResult;
    }

    @Override
    public List<OrgIdModel> queryOrgIdTreeList() {
        LambdaQueryWrapper<SysOrg> query = new LambdaQueryWrapper<SysOrg>();
        query.eq(SysOrg::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
        query.orderByAsc(SysOrg::getSortBy);
        List<SysOrg> list = this.list(query);
        // 调用wrapTreeDataToTreeList方法生成树状数据
        List<OrgIdModel> listResult = FindsOrgsChildrenUtil.wrapTreeDataToOrgIdTreeList(list);
        return listResult;
    }

    /**
     * saveOrgData 对应 add 保存用户在页面添加的新的机构对象数据
     */
    @Override
    @Transactional
    public void saveOrgData(SysOrg SysOrg, String username) {
        if (SysOrg != null && username != null) {
            if (SysOrg.getParentId() == null) {
                SysOrg.setParentId("");
            }
//			String s = UUID.randomUUID().toString().replace("-", "");
//			SysOrg.setId(s);
            // 先判断该对象有无父级ID,有则意味着不是最高级,否则意味着是最高级
            // 获取父级ID
            String parentId = SysOrg.getParentId();
            //update-begin--Author:baihailong  Date:20191209 for：机构编码规则生成器做成公用配置
            JSONObject formData = new JSONObject();
            formData.put("parentId",parentId);
            formData.put("org",true);
            String[] codeArray = (String[]) FillRuleUtil.executeOrgRule(FillRuleConstant.DEPART,formData);
            //update-end--Author:baihailong  Date:20191209 for：机构编码规则生成器做成公用配置
            SysOrg.setCode(codeArray[0]);
            SysOrg.setId(SysOrg.getCode());
            SysOrg.setCreateTime(new Date());
            SysOrg.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
            this.save(SysOrg);
        }

    }

    /**
     * updateOrgDataById 对应 edit 根据机构主键来更新对应的机构数据
     */
    @Override
    @Transactional
    public Boolean updateOrgDataById(SysOrg SysOrg, String username) {
        if (SysOrg != null && username != null) {
            SysOrg.setUpdateTime(new Date());
            SysOrg.setUpdateBy(username);
            this.updateById(SysOrg);
            return true;
        } else {
            return false;
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatchWithChildren(List<String> ids) {
        List<String> idList = new ArrayList<String>();
        for(String id: ids) {
            idList.add(id);
            this.checkChildrenExists(id, idList);
        }
        this.removeByIds(idList);
    }

    @Override
    public List<String> getSubIdsById(String id) {
        return this.baseMapper.getSubIdsById(id);
    }

    @Override
    public List<String> getMySubIdsById(String ids) {
        //根据机构id获取所负责机构
        String[] codeArr = this.getMyOrgParentCode(ids);
        return this.baseMapper.getSubIdsByCodes(codeArr);
    }

    /**
     * 根据机构id删除并且删除其可能存在的子级任何机构
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(String id) {
        List<String> idList = new ArrayList<>();
        idList.add(id);
        this.checkChildrenExists(id, idList);
        boolean ok = this.removeByIds(idList);
        return ok;
    }

    /**
     * delete 方法调用
     * @param id
     * @param idList
     */
    private void checkChildrenExists(String id, List<String> idList) {
        LambdaQueryWrapper<SysOrg> query = new LambdaQueryWrapper<SysOrg>();
        query.eq(SysOrg::getParentId,id);
        List<SysOrg> OrgList = this.list(query);
        if(OrgList != null && OrgList.size() > 0) {
            for(SysOrg Org : OrgList) {
                idList.add(Org.getId());
                this.checkChildrenExists(Org.getId(), idList);
            }
        }
    }

    /**
     * 根据用户所负责机构ids获取父级机构编码
     * @param OrgIds
     * @return
     */
    private String[] getMyOrgParentCode(String OrgIds){
        //根据机构ids查询所负责机构
        LambdaQueryWrapper<SysOrg> query = new LambdaQueryWrapper<SysOrg>();
        query.eq(SysOrg::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
        query.in(SysOrg::getId, Arrays.asList(OrgIds.split(",")));
        query.orderByAsc(SysOrg::getCode);
        List<SysOrg> list = this.list(query);
        //查找根机构
        if(list == null || list.size()==0){
            return null;
        }
        String sysCode = this.getMyOrgParentNode(list);
        String[] codeArr = sysCode.split(",");
        return codeArr;
    }

    /**
     * 获取负责机构父节点
     * @param list
     * @return
     */
    private String getMyOrgParentNode(List<SysOrg> list){
        Map<String,String> map = new HashMap<>();
        //1.先将同一公司归类
        for(SysOrg Org : list){
            String code = Org.getCode().substring(0,3);
            if(map.containsKey(code)){
                String mapCode = map.get(code)+","+Org.getCode();
                map.put(code,mapCode);
            }else{
                map.put(code,Org.getCode());
            }
        }
        StringBuffer parentCode = new StringBuffer();
        //2.获取同一公司的根节点
        for(String str : map.values()){
            String[] arrStr = str.split(",");
            parentCode.append(",").append(this.getMinLengthNode(arrStr));
        }
        return parentCode.substring(1);
    }

    /**
     * 获取同一公司中机构编码长度最小的机构
     * @param str
     * @return
     */
    private String getMinLengthNode(String[] str){
        int min =str[0].length();
        String sysCode = str[0];
        for(int i =1;i<str.length;i++){
            if(str[i].length()<=min){
                min = str[i].length();
                sysCode = sysCode+","+str[i];
            }
        }
        return sysCode;
    }


    @Override
    public List<Map<String, String>> getMyAll() {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<String> subIdsById = new ArrayList<>();
        if (!StringUtil.isNullOrEmpty(sysUser.getOrgCode())){
            subIdsById = getSubIdsById(sysUser.getOrgCode());
        }

        QueryWrapper queryWrapper = new QueryWrapper();
        if(subIdsById.size() > 0){
            queryWrapper.in("id",subIdsById);
        }
        List<SysOrg> SysOrgs =SysOrgMapper.selectList(queryWrapper);
        List<Map<String,String>> dataList= Lists.newArrayList();
        for (SysOrg SysOrg1:SysOrgs){
            Map<String,String> map =  Maps.newHashMap();
            map.put("label", SysOrg1.getName());
            map.put("value",SysOrg1.getId() );
            dataList.add(map);
        }
        return dataList;
    }

    @Override
    public List<Map<String, String>> getOrgCodeName() {
        QueryWrapper queryWrapper = new QueryWrapper();
        LoginUser sysUser=(LoginUser)SecurityUtils.getSubject().getPrincipal();
        queryWrapper.ne("status","0");
        List<SysOrg> sysOrgs = SysOrgMapper.selectList(queryWrapper);

        List<Map<String,String>> dataList= Lists.newArrayList();
        for (SysOrg sysOrg:sysOrgs){
            Map<String,String> map =  Maps.newHashMap();
            map.put("label", sysOrg.getName());
            map.put("value",sysOrg.getId());
            dataList.add(map);
        }
        return dataList;
    }

}
